package com.sjh.lib_app.net

import com.blankj.utilcode.util.EncryptUtils
import com.sjh.baseutils.phpHttpBuildQuery
import com.sjh.baseutils.phpKsort
import com.sjh.lib_app.AppConfig
import com.sjh.net.interceptor.BaseInterceptor
import okhttp3.*
import okio.Buffer
import org.json.JSONArray
import org.json.JSONObject
import java.net.URLDecoder
import java.util.*

/**
 * 签名拦截器
 * @author Extends
 * @date 2019/6/26/026
 */
class SignInterceptor: BaseInterceptor() {

    companion object{
        /**
         * 取消验签功能
         *
         * 在请求的header中添加，如果添加了该字段，则不参与验签操作
         */
        const val NO_SIGN_HEADER = "no_sign_header"
    }

    /**
     * 最大的字节数，如果超过限制则不进行验签，避免内容特别大的时候验签运算耗时太久
     * 注：get请求不在限制范围内
     */
    val maxByteNumber = 100 * 1024

    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()

        // 判断是否需要验签
        if (request.header(NO_SIGN_HEADER) != null){
            return chain.proceed(request.newBuilder().removeHeader(NO_SIGN_HEADER).build())
        }

        val map = getSignRequestParams(request)

        // 判断是否需要验签
        return if(map.isNullOrEmpty()){
            chain.proceed(request)
        }else{
            val str = phpHttpBuildQuery(map)+AppConfig.getSignToken()
            val sign = EncryptUtils.encryptSHA1ToString(str).toUpperCase()
            chain.proceed(request.newBuilder().addHeader("X-TOKEN", sign).build())
        }
    }

    /**
     * 获取验签用的数据集合
     */
    private fun getSignRequestParams(request: Request): SortedMap<String, Any>? {
        when(request.method().toUpperCase()){
            "GET" -> {
                val query = request.url()
                val size = query.querySize()
                val map = sortedMapOf<String,Any>()
                ( 0 until size).forEach {
                    map[query.queryParameterName(it)] = query.queryParameterValue(it)
                }
                return map
            }
            else -> {
                val requestBody = request.body()
                // 判断body内容是否超过限制大小
                if(requestBody != null && requestBody.contentLength() < maxByteNumber){
                    // 判断类型
                    if(requestBody is FormBody){
                        val map = sortedMapOf<String,Any>()
                        (0 until requestBody.size()).forEach {
                            map[URLDecoder.decode(requestBody.encodedName(it),"UTF-8")] = URLDecoder.decode(requestBody.encodedValue(it),"UTF-8")
                        }
                        return map
                    }else{
                        val buffer = Buffer()
                        requestBody.writeTo(buffer)
                        val content = buffer.readString(Charsets.UTF_8)
                        // 判断body内容是否是json
                        if(content[0] == '{' && content[0] == '}'){
                            return phpKsort(JSONObject(content))
                        }else if(content[0] == '[' && content[0] == ']') {
                            return phpKsort(JSONArray(content))
                        }
                    }
                }
            }
        }
        return null
    }
}